#pragma once

#include "opencv2/core/types.hpp"
#include "opencv2/highgui.hpp"
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <exception>
#include <fstream>
#include <iostream>
#include <iterator>
#include <opencv2/core/cvstd_wrapper.hpp>
#include <opencv2/core/hal/interface.h>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv4/opencv2/opencv.hpp>
#include <stdexcept>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <vector>
#include <unistd.h>
using str = std::string;
class basic_metro {
public:
	int width  = 1920; /* 横向宽度 */
	int height = 200;  /* 纵向高度 */
	basic_metro(
		const str& _station_file,
		int		   font_size,
		const str& font_path,
		const str& fontbd_path,
		const str& output) {
		if (output.ends_with('/'))
			output_fd = output;
		else
			output_fd = output + '/';
		system(("mkdir -p " + output_fd + ";rm -rf " + output_fd + "*").c_str());
		station_filename = _station_file;
		python_cmd = "python3 resource/main.py " + str(_station_file) + ' ' + font_path +
					 ' ' + fontbd_path + ' ' + std::to_string(font_size);
	}

	void basic_gen() {
		/* 运行python生成文件 */
		if (system(python_cmd.c_str()) != 0)
			throw std::runtime_error("run \"" + python_cmd + "\" failed.");
		station_init(station_filename.c_str());
		/* 检查是否生成了正确的数量*/
		std::ifstream info("/tmp/zzm/image/info.txt");
		int			  num;
		info >> num;
		if (num != station_list.size())
			throw std::runtime_error("python generated no correct file number.");
		/* 完成基本底图生成 */
		param_autogen();
		basic_image();
		/* 检测图形化界面，是pts则展示image */
		if (system("tty | grep pts >/dev/null") == 0) {
			try {
				cv::imshow("bacic pict", image);
				cv::waitKey();
			}
			catch (...) {
				std::cout << "[ FAILED ] \e[31;1mERROR: FAILED TO SHOW BASIC IMAGE.\e[0m"
						  << std::endl;
				std::cout << "[  INFO  ] Maybe you are not in a graphic console. "
							 "Function imshow() cannot continue."
						  << std::endl;
				std::cout << "[  INFO  ] Exception std::exception is caught and handled. "
							 "Photo will continue to generate."
						  << std::endl;
			}
		}
	}

	void image_gen() {
		for (int index = 0; index < station_list.size(); index++) {
			using std::to_string;
			const str file_name_base =
				output_fd + to_string(index) + '-' + station_list[index];
			image_generate(index, false, false);
			cv::imwrite(file_name_base + "-1.png", _image);
			image_generate(index, false, true);
			cv::imwrite(file_name_base + "-2.png", _image);
			if (index + 1 == station_list.size()) break;
			image_generate(index, true, false);
			cv::imwrite(file_name_base + "-3.png", _image);
			image_generate(index, true, true);
			cv::imwrite(file_name_base + "-4.png", _image);
		}
		return;
	}

	~basic_metro() {
		system("rm -rf /tmp/zzm/image");
	}
	/* 自定义颜色 */
	static cv::Scalar line_color;	 /* 线路颜色 */
	static cv::Scalar passed_light;	 /* 过站闪灯 */
	static cv::Scalar before_light;	 /* 未过站闪灯 */
	static cv::Scalar now_st_light;	 /* 当前车站颜色 */
	static cv::Scalar section_light; /* 区间闪灯颜色 */
	std::vector<str>  station_list;
	str				  output_fd;
	str				  station_filename;
	str				  python_cmd;
	str				  base_map;

private:
	cv::Mat image, _image;
	/* 站点信息 */
	int station_begin;		 /* 圆心开始 */
	int station_inner_r;	 /* 内圆半径 */
	int station_outer_r;	 /* 外圆半径 */
	int station_light_point; /* 光点半径 */
	int station_numbers;	 /* 站点数量 */
	/* 线路信息 */
	int line_length;		/* 相邻站点间距 */
	int line_thick;			/* 线路粗细 */
	int line_point_counter; /* 相邻站点间光点数量 */
	int line_point_section; /* 相邻光点间距 */
	int line_point_outer_r; /* 光点外半径 */
	int line_point_inner_r; /* 光点内半径 */
	/* 颜色信息 */
	static const cv::Scalar white, gray, black, yellow;

	/**
	 * @brief 完成底图绘制
	 *
	 */
	void basic_image();

	/**
	 * @brief 在底图上添上闪灯
	 *
	 * @param station_passed 过去的车站（不含停在站内）
	 * @param in_section 是否在区间内
	 * @param now_light_on 对应的灯是否亮起
	 */
	void
	light_on(const int station_passed, const bool in_section, const bool now_light_on);

	/**
	 * @brief 完成底图的文字绘制
	 *
	 */
	void word_on();

	/**
	 * @brief 读取车站信息
	 *
	 * @param filename 车站站名
	 */
	void station_init(const char* filename) {
		std::ifstream			   istr(filename);
		std::istream_iterator<str> stations(istr);
		decltype(stations)		   eof;
		while (stations != eof) station_list.push_back(*stations++);
	}

	/**
	 * @brief 生成成图
	 *
	 * @param station_passed 已经通过的车站
	 * @param in_section 是否在区间里
	 * @param now_light_on 这个位置是否亮灯
	 */
	void image_generate(
		const int  station_passed,
		const bool in_section,
		const bool now_light_on) {
		_image = image.clone();
		light_on(station_passed, in_section, now_light_on);
	}

	/**
	 * @brief 自动生成参数
	 *
	 */
	void param_autogen();
};
